home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / umddvi / dev / dmd-sp.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  14KB  |  569 lines

  1. /*
  2.  * Support drawing routines for Chris Torek's DVI->ImPress program.
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include "types.h"
  8. #include "dmdcodes.h"
  9.  
  10. /* Put a two-byte (word) value to the Imagen */
  11. #define putword(w) (putchar((w) >> 8), putchar(w))
  12.  
  13. extern char *malloc();
  14.  
  15.  
  16. #define    TRUE    1
  17. #define    FALSE    0
  18.  
  19. #define    PI        3.14157926536
  20. #define    TWOPI        (PI*2.0)
  21. #define    MAXPOINTS    300    /* Most number of points in a path */
  22.  
  23.  
  24. /* Graphics operations */
  25. #define    WHITE    0
  26. #define    SHADE    3
  27. #define    OR    7
  28. #define    BLACK    15
  29.  
  30. extern    double    cos(), sin(), sqrt();
  31. extern    int    DPI;        /* Resolution of device */
  32. #define    PixPerInX    DPI
  33. #define    PixPerInY    DPI
  34.  
  35. extern    int    UserMag;
  36. #define    fconv(x, f)\
  37.     (((double)(x)/1000.0) * ((double)(f)) * ((double)UserMag/1000.0))
  38. #define    conv(x, f)\
  39.     ((int) ((((double)(x)/1000.0) * ((double)(f)) * ((double)UserMag/1000.0)) + 0.5))
  40. #define    xconv(x)    conv(x, PixPerInX)
  41. #define    yconv(y)    conv(y, PixPerInY)
  42.  
  43. extern int    ImHH;        /* Imagen horizontal position */
  44. extern int    ImVV;        /* Imagen vertical position */
  45. extern int    hh;        /* current horizontal position, in DEVs */
  46. extern int    vv;        /* current vertical position, in DEVs */
  47.  
  48.  
  49. static    int xx[MAXPOINTS], yy[MAXPOINTS], pathlen,
  50.     pensize = 1;    /* Size we want Imagen to draw at, default 2 pixels */
  51.  
  52. #define    MAXPENSIZE 20        /* Imagen restriction */
  53.  
  54. static int
  55.     family_defined = FALSE,    /* Have we chosen family yet? */
  56.     texture_defined = FALSE,/* Have we done a set_texture yet? */
  57.     whiten_next = FALSE,    /* Should next object be whitened? */
  58.     blacken_next = FALSE,    /* Should next object be blackened? */
  59.     shade_next = FALSE;    /* Should next object be shaded? */
  60.  
  61. /* Predefined shading (texture) glyph */
  62. /* First, define size of glyph */
  63. #define    THEIGHT    32        /* bits high */
  64. #define    TWIDTH    4        /* bytes wide */
  65. /* Next, declare the bit map for the glyph */
  66. static char stexture[THEIGHT][TWIDTH]={
  67.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  68.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  69.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  70.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  71.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  72.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  73.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  74.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  75.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  76.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  77.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  78.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  79.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  80.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  81.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  82.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
  83.  
  84. /*
  85.  * Copy a default texture into the stexture array
  86.  */
  87. static void glyph_init()
  88. {
  89.     static char btexture[THEIGHT][TWIDTH]={
  90.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  91.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  92.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  93.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  94.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  95.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  96.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  97.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  98.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  99.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  100.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  101.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  102.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  103.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00},
  104.     {0xcc, 0xcc, 0xcc, 0xcc}, {0x00, 0x00, 0x00, 0x00},
  105.     {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}};
  106.  
  107.     int i;
  108.     for (i=0; i<THEIGHT; i++)
  109.         bcopy(btexture[i],stexture[i],TWIDTH);
  110.  
  111. }
  112.  
  113. #define    push_location()
  114. #define    pop_location()
  115.  
  116. #ifdef notdef
  117. /*
  118.  * Push the state of the Imagen and set up a new virtual coord system
  119.  */
  120. static void push_location()
  121. {
  122.     putchar(imP_Push);
  123.     putchar(imP_SetHVSystem);
  124.     putchar(0140);
  125. }
  126.  
  127.  
  128. /*
  129.  * Create the pushed virtual page, and pop the state of the printer
  130.  */
  131. static void pop_location()
  132. {
  133.     putchar(imP_Pop);
  134. }
  135. #endif
  136.  
  137.  
  138. /*
  139.  * Set the pen size
  140.  * Called as \special{pn size}
  141.  *     eg: \special{pn 8}
  142.  * The size is the number of milli-inches for the diameter of the pen.
  143.  * This routine converts that value to device-dependent pixels, and makes
  144.  * sure that the resulting value is within legal bounds.
  145.  */
  146. static void im_pensize(cp)
  147. char *cp;
  148. {
  149.     int size;
  150.     
  151.     if (sscanf(cp, " %d ", &size) != 1) return;
  152.     pensize = yconv(size);
  153.     if (pensize < 1) pensize = 1;
  154.     else if (pensize > MAXPENSIZE) pensize = MAXPENSIZE;
  155. }
  156.  
  157.  
  158. /*
  159.  * Make sure the pen size is set.  Since we push and pop the state,
  160.  * this has to be sent for each different object (I think).
  161.  */
  162. static void set_pen_size()
  163. {
  164.     putchar(DMD_PENSIZE);
  165.     putchar(pensize);
  166. }
  167.  
  168.  
  169. /*
  170.  * Actually apply the attributes (shade, whiten, or blacken) to the currently
  171.  * defined path/figure.
  172.  */
  173. static void do_attributes()
  174. {
  175.     static int family;        /* Family of downloaded texture glyph */
  176.     static int member;        /* Member of family */
  177.     int i,j;            /* Loop through glyph array */
  178.  
  179.     if (shade_next) {
  180.     shade_next = FALSE;
  181. #ifdef notdef
  182.     if (!family_defined) {
  183.         family_defined = TRUE;
  184.         family = fnum++;
  185.         member = -1;
  186.     }
  187.     if (!texture_defined) {
  188.         texture_defined = TRUE;
  189.         member++;
  190.         putchar(imP_DefGlyph);
  191.         putchar((family & 0x7e) >> 1);
  192.         putchar((family & 0x01) << 7 | (member & 0x7f));
  193.         /*putword(0); */        /* Advance width */
  194.         putword(32);
  195.         putword(TWIDTH*8);    /* pixel width (8 x number of bytes) */
  196.         /*putword(0); */        /* left offset */
  197.         putword(32);
  198.         putword(THEIGHT);    /* and height of glyph */
  199.         /*putword(0); */        /* top offset */
  200.         putword(32);
  201.         for (i=0; i<THEIGHT; i++)/* Do rows */
  202.         for (j=0; j<TWIDTH; j++) putchar(stexture[i][j]);
  203.     }
  204.     putchar(imP_SetTexture);
  205.     putchar((family & 0x7e) >> 1);
  206.     putchar((family & 0x01) << 7 | (member & 0x7f));
  207. #endif
  208.     putchar(DMD_FILLPATH);
  209.     putchar(SHADE);
  210.     glyph_init(); /* reinitialize the array */
  211.     }
  212.     else if (whiten_next) {
  213.     whiten_next = FALSE;
  214.     putchar(DMD_FILLPATH);
  215.     putchar(WHITE);
  216.     }
  217.     else if (blacken_next) {
  218.     blacken_next = FALSE;
  219.     putchar(DMD_FILLPATH);
  220.     putchar(BLACK);
  221.     }
  222. }
  223.  
  224.  
  225. /*
  226.  * Flush the path that we've built up with im_drawto()
  227.  * Called as \special{fp}
  228.  */
  229. static void im_flushpath()
  230. {
  231.     register int i;
  232.  
  233.     push_location();
  234.     if (pathlen <= 0) return;
  235.     set_pen_size();
  236.     putchar(DMD_SEGMENT);
  237.     putword(pathlen);
  238.     for (i=1; i<=pathlen; i++) {
  239.     putword(xx[i]);
  240.     putword(yy[i]);
  241.     }
  242.     pathlen = 0;
  243.     putchar(DMD_DRAWPATH);
  244.     putchar(BLACK);
  245.     do_attributes();
  246.     pop_location();
  247. }
  248.  
  249.  
  250. /* Helper routine for dashed_line() */
  251. static void connect(x0, y0, x1, y1)
  252. int x0, y0, x1, y1;
  253. {
  254.     set_pen_size();
  255.     putchar(DMD_SEGMENT);
  256.     putword(2);        /* Path length */
  257.     putword(x0);    putword(y0);/* The path */
  258.     putword(x1);    putword(y1);
  259.     putchar(DMD_DRAWPATH);
  260.     putchar(BLACK);
  261. }
  262.  
  263.  
  264. /* Another helper.  Draw a dot at the indicated point */
  265. static void dot_at(x, y)
  266. int x,y;
  267. {
  268.     set_pen_size();
  269.     putchar(DMD_SEGMENT);
  270.     putword(1);            /* Path length */
  271.     putword(x);    putword(y);    /* The path */
  272.     putchar(DMD_DRAWPATH);
  273.     putchar(BLACK);
  274. }
  275.  
  276.  
  277. /*
  278.  * Draw a dashed or dotted line between the first pair of points in the array
  279.  * Called as \special{da <inchesperdash>}    (dashed line)
  280.  *      or \special{dt <inchesperdot>}    (dotted line)
  281.  *    eg:  \special{da 0.05}
  282.  */
  283. static void dashed_line(cp, dotted)
  284. char *cp;
  285. int dotted;            /* boolean */
  286. {
  287.     int i, numdots, x0, y0, x1, y1;
  288.     double cx0, cy0, cx1, cy1;
  289.     double d, spacesize, a, b, dx, dy, pixperdash;
  290.     float inchesperdash;
  291.  
  292.     if (sscanf(cp, " %f ", &inchesperdash) != 1) return;
  293.     if (pathlen <= 1) return;
  294.     pixperdash = inchesperdash * ((float) PixPerInY);
  295.     if (pixperdash < 2.)
  296.     pixperdash = 2.;
  297.     x0 = xx[1]; x1 = xx[2];
  298.     y0 = yy[1]; y1 = yy[2];
  299.     dx = x1 - x0;
  300.     dy = y1 - y0;
  301.     push_location();
  302.     if (dotted) {
  303.     numdots = sqrt(dx*dx + dy*dy) / pixperdash + 0.5;
  304.     if (numdots > 0)
  305.         for (i = 0; i <= numdots; i++) {
  306.         a = (float) i / (float) numdots;
  307.         cx0 = ((float) x0) + (a*dx) + 0.5;
  308.         cy0 = ((float) y0) + (a*dy) + 0.5;
  309.         dot_at((int) cx0, (int) cy0);
  310.         }
  311.     }
  312.     else {
  313.     d = sqrt(dx*dx + dy*dy);
  314.     if (d <= 2 * pixperdash) {
  315.         connect(x0, y0, x1, y1);
  316.         pathlen = 0;
  317.         pop_location();
  318.         return;
  319.     }
  320.     numdots = d / (2 * pixperdash) + 1;
  321.     spacesize = (d - numdots * pixperdash) / (numdots - 1);
  322.     for (i=0; i<numdots-1; i++) {
  323.         a = i * (pixperdash + spacesize) / d;
  324.         b = a + pixperdash / d;
  325.         cx0 = ((float) x0) + (a*dx) + 0.5;
  326.         cy0 = ((float) y0) + (a*dy) + 0.5;
  327.         cx1 = ((float) x0) + (b*dx) + 0.5;
  328.         cy1 = ((float) y0) + (b*dy) + 0.5;
  329.         connect((int) cx0, (int) cy0, (int) cx1, (int) cy1);
  330.         b += spacesize / d;
  331.     }
  332.     cx0 = ((float) x0) + (b*dx) + 0.5;
  333.     cy0 = ((float) y0) + (b*dy) + 0.5;
  334.     connect((int) cx0, (int) cy0, x1, y1);
  335.     }
  336.     pathlen = 0;
  337.     pop_location();
  338. }
  339.  
  340.  
  341. /*
  342.  * Virtually draw to a given x,y position on the virtual page.
  343.  * X and Y are expressed in thousandths of an inch, and this
  344.  * routine converts them to pixels.
  345.  *
  346.  * Called as \special{pa <x> <y>}
  347.  *     eg:  \special{pa 0 1200}
  348.  */
  349. static void im_drawto(cp)
  350. char *cp;
  351. {
  352.     int x,y;
  353.  
  354.     if (sscanf(cp, " %d %d ", &x, &y) != 2) return;
  355.  
  356.     if (++pathlen >= MAXPOINTS)
  357.     error(1, 0, "Too many points specified");
  358.     xx[pathlen] = xconv(x) + ImHH;
  359.     yy[pathlen] = yconv(y) + ImVV;
  360. }
  361.  
  362. /* Same routine as above, but it uses the special graphics primitives */
  363. static void im_arc(cp)
  364. char *cp;
  365. {
  366.     int xc, yc, xrad, yrad;
  367.     float start_angle, end_angle, fxrad, fyrad;
  368.     int xp, yp;
  369.  
  370.     if (sscanf(cp, " %d %d %d %d %f %f ", &xc, &yc, &xrad, &yrad, &start_angle,
  371.     &end_angle) != 6) return;
  372.     push_location();
  373.     set_pen_size();
  374.     xc = xconv(xc) + ImHH;
  375.     yc = yconv(yc) + ImVV;
  376.     {
  377.     double temp;
  378.     temp = start_angle;
  379.         start_angle = end_angle;
  380.         end_angle = temp;
  381.     }
  382.     if (xrad >= yrad-1 && xrad <= yrad+1) {        /* Circle or arc */
  383.     putchar(DMD_CIRCLE);
  384.     putword(xc); putword(yc);
  385.     /* starting point */
  386.     fyrad = fconv(yrad, PixPerInY);
  387.     xp = fyrad * cos(start_angle) + xc + .5;
  388.     yp = fyrad * sin(start_angle) + yc + .5;
  389.     putword(xp); putword(yp);
  390.     /* finishing point */
  391.     xp = fyrad * cos(end_angle) + xc + .5;
  392.     yp = fyrad * sin(end_angle) + yc + .5;
  393.     putword(xp); putword(yp);
  394.     }
  395.     else {            /* Ellipse */
  396.     putchar(DMD_ELLIPSE);
  397.     putword(xc); putword(yc);
  398.     /* starting point */
  399.     fxrad = fconv(xrad, PixPerInX);
  400.     fyrad = fconv(yrad, PixPerInY);
  401.     xp = fxrad * cos(start_angle) + xc + .5;
  402.     yp = fyrad * sin(start_angle) + yc + .5;
  403.     putword(xp); putword(yp);
  404.     /* finishing point */
  405.     xp = fxrad * cos(end_angle) + xc + .5;
  406.     yp = fyrad * sin(end_angle) + yc + .5;
  407.     putword(xp); putword(yp);
  408.     putword(xconv(xrad));
  409.     putword(yconv(yrad));
  410.     }
  411.     putchar(DMD_DRAWPATH);
  412.     putchar(BLACK);
  413.     do_attributes();
  414.     pop_location();
  415. }
  416.  
  417.  
  418. /*
  419.  * Create a spline through the points in the array.
  420.  * Called like flush path (fp) command, after points
  421.  * have been defined via pa command(s).
  422.  *
  423.  * eg:    \special{sp}
  424.  */
  425. static void flush_spline()
  426. {
  427.     register int i;
  428.  
  429.     push_location();
  430.     if (pathlen <= 0) return;
  431.     set_pen_size();
  432.     putchar(DMD_SPLINE);
  433.     putword(pathlen);
  434.     for (i=1; i<=pathlen; i++) {
  435.     putword(xx[i]);
  436.     putword(yy[i]);
  437.     }
  438.     pathlen = 0;
  439.     putchar(DMD_DRAWPATH);
  440.     putchar(BLACK);
  441.     do_attributes();
  442.     pop_location();
  443. }
  444.  
  445.  
  446. /*
  447.  * Whiten the interior of the next figure (path).  Command is:
  448.  *    \special{wh}
  449.  */
  450. static void im_whiten()
  451. {
  452.     whiten_next = TRUE;
  453. }
  454.  
  455.  
  456. /*
  457.  * Blacken the interior of the next figure (path).  Command is:
  458.  *    \special{bk}
  459.  */
  460. static void im_blacken()
  461. {
  462.     blacken_next = TRUE;
  463. }
  464.  
  465.  
  466. /*
  467.  * Shade the interior of the next figure (path) with the predefined
  468.  * texture.  Command is:
  469.  *    \special{sh}
  470.  */
  471. static void im_shade()
  472. {
  473.     shade_next = TRUE;
  474. }
  475.  
  476.  
  477. /*
  478.  * Define the texture array.  Command is:
  479.  *    \special{tx 32bits 32bits ....}
  480.  */
  481. static void im_texture(pcount,bitpattern)
  482. int pcount, bitpattern[32];
  483. {
  484.     int i,j,k;
  485.     unsigned long ul_one;
  486.  
  487. #ifdef notdef
  488. #ifdef    DEBUG
  489.     if (sizeof ul_one != TWIDTH)
  490.     error(1, 0, "pointer/size mismatch");
  491. #endif
  492.     j = 0;
  493.     for (k=0; k < THEIGHT/pcount; k++) {
  494.     for (i=0; i<pcount; i++) {
  495.         ul_one = htonl((unsigned long) bitpattern[i]);
  496.         bcopy((char *) &ul_one, stexture[j++], TWIDTH);
  497.     }
  498.     }
  499.     texture_defined = FALSE;
  500. #endif
  501. }
  502.  
  503.  
  504. /*
  505.  * This routine takes the string argument for a tx command and
  506.  * parses out the separate bitpatterns to call im_texture with.
  507.  * Written by Tinh Tang
  508.  */
  509. static void do_texture(t)
  510. char *t;
  511. {
  512.     int bitpattern[32];
  513.     int pcount = 0;
  514.  
  515.     while (isspace (*t)) t++;
  516.     while (*t) {
  517.     if (sscanf(t, "%x", &bitpattern[pcount++]) != 1) {
  518.         error(0, 0, "malformed tx command");
  519.         return;
  520.     }
  521.     while (*t && !isspace(*t)) t++;/* Skip to space */
  522.     while (*t && isspace(*t)) t++;/* Skip to nonspace */
  523.     }
  524.     if (pcount != 4 && pcount != 8 && pcount != 16 && pcount != 32) {
  525.     error(0, 0, "malformed tx command");
  526.     return;
  527.     }
  528.     im_texture(pcount, bitpattern);
  529. }
  530.  
  531.     
  532. #define    COMLEN    3        /* Length of a tpic command plus one */
  533.  
  534. DoSpecial(k)
  535.     i32 k;
  536. {
  537.     char *spstring, *cp, command[COMLEN];
  538.     register int len;
  539.  
  540.     spstring = malloc((unsigned) (k+1));
  541.     if (spstring == NULL) error(2, 0, "Out of memory");
  542.     len = 0;
  543.     while (k--) spstring[len++] = GetByte(stdin);
  544.     spstring[len] = '\0';
  545.     cp = spstring;
  546.     while (isspace(*cp)) ++cp;
  547.     len = 0;
  548.     while (!isspace(*cp) && *cp && len < COMLEN-1) command[len++] = *cp++;
  549.     command[len] = '\0';
  550.  
  551.     if (ImHH != hh || ImVV != vv)
  552.         ImSetPosition(hh, vv);
  553.  
  554.     if (strcmp(command, "pn") == 0) im_pensize(cp);
  555.     else if (strcmp(command, "fp") == 0) im_flushpath();
  556.     else if (strcmp(command, "da") == 0) dashed_line(cp, 0);
  557.     else if (strcmp(command, "dt") == 0) dashed_line(cp, 1);
  558.     else if (strcmp(command, "pa") == 0) im_drawto(cp);
  559.     else if (strcmp(command, "ar") == 0) im_arc(cp);
  560.     else if (strcmp(command, "sp") == 0) flush_spline();
  561.     else if (strcmp(command, "sh") == 0) im_shade();
  562.     else if (strcmp(command, "wh") == 0) im_whiten();
  563.     else if (strcmp(command, "bk") == 0) im_blacken();
  564.     else if (strcmp(command, "tx") == 0) im_texture(cp);
  565.     else error(0, 0, "warning: ignoring \\special");
  566.  
  567.     free(spstring);
  568. }
  569.